package me.youline.dataServer.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.Pattern;

import me.youline.dataServer.ConfigConstants;
import me.youline.dataServer.controller.dto.IdPaginationDTO;
import me.youline.dataServer.controller.dto.UserRelationStatusDTO;
import me.youline.dataServer.controller.dto.UserSocialRelFrontDTO;
import me.youline.dataServer.entity.UserSocialRelation;
import me.youline.dataServer.entity.UserToken;
import me.youline.dataServer.exception.ReplicatedDataException;
import me.youline.dataServer.exception.UnExistDataException;
import me.youline.dataServer.service.SocialRelationService;
import me.youline.dataServer.service.account.UserAccountService;
import me.youline.dataServer.service.authentication.UserTokenService;
import me.youline.dataServer.service.front.IdPageDTOAdapter;
import me.youline.dataServer.service.front.SocialRelationDTOAdapter;
import me.youline.dataServer.service.front.UserInfoDTOAdapter;
import me.youline.dataServer.service.support.LogMsgBuilder;
import me.youline.dataServer.service.support.MsgBuilder;
import me.youline.dataServer.utils.IdPagination;
import me.youline.dataServer.utils.ResponseTypeOutputUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 用户社交关系业务控制器
 * @author linhan
 *
 */
@RequestMapping("/socialRel")
@Controller
public class UserSocialRelationController {
	
	private static Logger logger = LoggerFactory.getLogger(UserSocialRelationController.class);
	
	@Autowired
	private UserTokenService userTokenService;
	
	@Autowired
	private SocialRelationService socialService;
	
	@Autowired
	private UserInfoDTOAdapter assembler;
	
	@Autowired
	private SocialRelationDTOAdapter socialRelationDTOAssembler;
	
	@Autowired
	private UserAccountService accountService;
	
	/**
	 * 关注指定用户
	 * @param toUserId
	 * @param userTokenStr
	 * @param response
	 */
	@RequestMapping(value="/{toUserId}",method=RequestMethod.POST)
	public void followTargetUser(@PathVariable Long toUserId, @RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String userTokenStr,HttpServletResponse response){
		UserToken token = userTokenService.getUserTokenByTokenStr(userTokenStr);
		try {
			if(token.getUserId().equals(toUserId)){
				response.setStatus(HttpServletResponse.SC_FORBIDDEN);
				ResponseTypeOutputUtils.renderJson(response,MsgBuilder.error().errorCode("200203").errorMsg("不得关注自己").toJSONString());
				return;
			}
			socialService.buildSocialRelation(token.getUserId(), toUserId);
			UserRelationStatusDTO relStatusDTO = getRelStatusAfterBuildRel(toUserId,token.getUserId());
			response.setStatus(HttpServletResponse.SC_CREATED);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success().addObj("relStatus", relStatusDTO).toJSONString());
			return;
		} catch (ReplicatedDataException | UnExistDataException e) {
			if(e instanceof ReplicatedDataException){
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("200201").errorMsg("已经关注指定的用户").toJSONString());
				return;
			}
			if(e instanceof UnExistDataException){
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				ResponseTypeOutputUtils.renderJson(response,MsgBuilder.error().errorCode("200202").errorMsg("关注的用户已经不存在").toJSONString());
				return;
			}
		}catch(Exception e){
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("关注用户业务执行失败").toJSONString());
			return;
		}
	}
	
	/**
	 * 取消对指定用户的关注
	 * @param targetUserId
	 * @param userTokenStr
	 * @param response
	 */
	@RequestMapping(value = "/{targetUserId}",method = RequestMethod.DELETE)
	public void deleteFollowingRel(@PathVariable Long targetUserId,@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String userTokenStr,HttpServletResponse response){
		try {
			UserToken token = userTokenService.getUserTokenByTokenStr(userTokenStr);
			Long userId = token.getUserId();
			socialService.cancelFollowingRelation(userId, targetUserId);
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success().toJSONString());
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("删除关注关系业务失败").toJSONString());
			return;
		}
	}
	
	/**
	 * 获取目标用户的粉丝列表
	 * @param targetUserId
	 * @param response
	 * @param idPage
	 */
	@RequestMapping(value="/{targetUserId}/followers",method = RequestMethod.GET)
	public void getFollowers(@PathVariable Long targetUserId,@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String userTokenStr,HttpServletResponse response,@ModelAttribute IdPaginationDTO idPage){
		UserToken token = null;
		try {
			token = userTokenService.getUserTokenByTokenStr(userTokenStr);
			IdPagination idPagination = IdPageDTOAdapter.getPagination(idPage);
			List<UserSocialRelation> list = socialService.doGetUserFollowerRelation(targetUserId, idPagination);
			UserSocialRelFrontDTO relDTO = socialRelationDTOAssembler.getFollowerList(token.getUserId(), targetUserId, list);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success().addObj("rel",relDTO).toJSONString());
		} catch (Exception e) {
			logger.error(LogMsgBuilder.build().error().module("socialRelation").interfaceName("getFollowers").msg("get followers fail - "+e.getMessage()).detail("targetId:"+targetUserId+",viewUserId:"+(token==null ? "":token.getUserId())).getLogInfo(), e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("获取粉丝列表业务执行失败"));
		}
	}
	
	/**
	 * 获取目标用户的关注人列表
	 * @param targetUserId
	 * @param response
	 * @param idPage
	 */
	@RequestMapping(value="/{targetUserId}/followings",method = RequestMethod.GET)
	public void getFollowings(@PathVariable Long targetUserId,@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String userTokenStr,HttpServletResponse response,@ModelAttribute IdPaginationDTO idPage){
		UserToken token = null;
		try {
			token = userTokenService.getUserTokenByTokenStr(userTokenStr);
			IdPagination idPagination = IdPageDTOAdapter.getPagination(idPage);
			List<UserSocialRelation> list = socialService.doGetUserFollowingRelation(targetUserId, idPagination);
			UserSocialRelFrontDTO relDTO = socialRelationDTOAssembler.getFollowingList(token.getUserId(), targetUserId, list);
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success().addObj("rel",relDTO).toJSONString());
			return ;
		} catch (Exception e) {
			logger.error(LogMsgBuilder.build().error().module("socialRelation").interfaceName("getFollowings").msg("get followings fail - " + e.getMessage()).detail("targetId:"+targetUserId+",viewUserId:"+(token==null ? "":token.getUserId())).getLogInfo(), e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("获取关注人列表业务执行失败"));
			return;
		}
	}
	
	/**
	 * 获取目标用户的关注人数及粉丝人数
	 * @param targetUserId
	 * @param response
	 */
	@RequestMapping(value = "/{targetUserId}/total",method = RequestMethod.GET)
	public void getFollowerAndFollowingNum(@PathVariable Long targetUserId,HttpServletResponse response){
		try {
			int followingNum = socialService.getFollowingTotal(targetUserId);
			int followerNum = socialService.getFollowerTotal(targetUserId);
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success().addObj("followingNum", followingNum).addObj("followerNum", followerNum).toJSONString());
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("获取关注人数及粉丝人数业务失败").toJSONString());
			return;
		}
	}
	
	
	/**
	 * 获取推荐用户列表
	 * @param response
	 */
	@RequestMapping(value="/recommend",method = RequestMethod.GET)
	public void getRecommendUsers(@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String userTokenStr,HttpServletResponse response){
		try {
			UserToken token = userTokenService.getUserTokenByTokenStr(userTokenStr);
			UserSocialRelFrontDTO relDTO = socialRelationDTOAssembler.getSocialRelDTOForUser(token.getUserId(), socialService.getRecommendUserList());
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response,MsgBuilder.success().addObj("recommends", relDTO).toJSONString());
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("获取推荐用户列表业务执行失败").toJSONString());
			return;
		}
	}
	
	/**
	 * 根据用户名查询用户信息
	 * @param telephone
	 * @param tokenStr
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="/search",method = RequestMethod.GET)
	public void searchAccount(@Valid @Pattern(regexp="1[34578]\\d{9}$")@RequestParam String userName, @RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String tokenStr,HttpServletRequest request,HttpServletResponse response){
			try {
				UserToken token = userTokenService.getUserTokenByTokenStr(tokenStr);
				List<Long> list = accountService.searchAccountByUserName(userName);
				UserSocialRelFrontDTO relDTO = socialRelationDTOAssembler.getSocialRelDTOForUser(token.getUserId(), list);
				response.setStatus(HttpServletResponse.SC_OK);
				ResponseTypeOutputUtils.renderJson(response,MsgBuilder.success().addObj("rel", relDTO).toJSONString());
				return;
			} catch (Exception e) {
				logger.error(e.getMessage(),e);
				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
				ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error().errorCode("100001").errorMsg("搜索用户业务执行失败").toJSONString());
				return;
			}
	}
	
	private UserRelationStatusDTO getRelStatusAfterBuildRel(Long toUserId,Long fromUserId){
		UserRelationStatusDTO dto = new UserRelationStatusDTO();
		dto.setCurrentUserId(toUserId);
		dto.setTargetUserId(fromUserId);
		dto.setIsFollowed(true);
		dto.setIsFollowing(socialService.isFollowing(toUserId, fromUserId));
		return dto;
	}
	
}
